package persistence;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;

import model.Instituicao;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Expression;


public class InstituicaoDAO implements IDAO {

	private static InstituicaoDAO instance = null;
	
	private Session session;
	
	private Transaction transaction;

	private InstituicaoDAO() {	}

	public static InstituicaoDAO getInstance() {
		if (instance == null) {
			instance = new InstituicaoDAO();
		}
		return instance;
	}

	public Collection<Object> getTodos() {
		List<Object> instituicoes = new ArrayList<Object>();
		session = HibernateSessionFactory.currentSession();
		transaction = session.beginTransaction();
		
		try {
			instituicoes = session.createQuery("SELECT b FROM Instituicao AS b ORDER BY b.id").list();
			transaction.commit();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {		
			HibernateSessionFactory.closeSession();
		}

		return instituicoes;
	}

	private boolean allEmpty(Instituicao i) {
		return isEmptyField(i.getNome()) && 
			   isEmptyField(i.getMunicipio()) &&
			   isEmptyField(i.getResponsavel()) &&
			   isEmptyField(i.getResponsavelArea());		 
	}
	
	private boolean isEmptyField(String field) {
		return field == null || "".equals(field);
	}

	public Collection<Object> getInstituicoesAccordingTo(Instituicao i) {
		List<Object> instituicoesMatching = new ArrayList<Object>();
		session = HibernateSessionFactory.currentSession();
		transaction = session.beginTransaction();
		
		try {
			if (allEmpty(i)) {
				instituicoesMatching = session.createQuery("SELECT i FROM Instituicao as i").list();
			} else {			
				Criteria c = session.createCriteria(Instituicao.class);
				if (i.getNome() != null) {
					c.add(Expression.like("nome", i.getNome()));
				} 
				if (i.getMunicipio() != null) {
					c.add(Expression.like("municipio", i.getMunicipio()));
				}
				if (i.getResponsavel() != null) {
					c.add(Expression.like("responsavel", i.getResponsavel()));
				}
				if (i.getResponsavelArea() != null) {
					c.add(Expression.like("responsavelArea", i.getResponsavelArea()));
				}
				instituicoesMatching = c.list();
			}
			transaction.commit();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			HibernateSessionFactory.closeSession();
		}		
		
		return instituicoesMatching;
	}

	public Instituicao getPorChavePrimaria(Object chavePrimaria) {
		Instituicao instituicao = null;
		Session session = HibernateSessionFactory.currentSession();
		Transaction transaction = session.beginTransaction();
		
		try{
			Long chave = (Long) chavePrimaria;
			instituicao = (Instituicao) session.get(Instituicao.class, chave);
			transaction.commit();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			HibernateSessionFactory.closeSession();
		}
		
		return instituicao;
	}
	
	public Instituicao getInstituicaoPorNome(String nome) {
		Collection<Object> inst = new HashSet<Object>(getTodos());
		for (Object obj : inst) {
			Instituicao insti = (Instituicao) obj;
			if (insti.getNome().equals(nome)) {
				return insti;
			}
		}		
		return null;
	}

	public void salvar(Object instituicao) {
		session = HibernateSessionFactory.currentSession();
		transaction = session.beginTransaction();	
		
		try{
			session.save(instituicao);
			transaction.commit();			
		} catch (Exception e) {			
			e.printStackTrace();
		} finally {
			HibernateSessionFactory.closeSession();
		}		
	}
	
	public void alterar(Object obj) {
		session = HibernateSessionFactory.currentSession();
		transaction = session.beginTransaction();
		try {
			Instituicao instituicaoNew = (Instituicao) obj;
			session.saveOrUpdate(instituicaoNew);
			transaction.commit();						
		} catch (Exception e) {			
			e.printStackTrace();
		} finally {
			HibernateSessionFactory.closeSession();
		}		
	}

	public void remover(Object chavePrimaria) {
		session = HibernateSessionFactory.currentSession();
		transaction = session.beginTransaction();
		try {
			Instituicao instituicao = (Instituicao) session.get(Instituicao.class, (Long) chavePrimaria);
			session.delete(instituicao);			
			transaction.commit();			
		} catch (Exception e) {			
			e.printStackTrace();
		} finally {
			HibernateSessionFactory.closeSession();
		}		
	}

}
